/* Graphic visualizer implementation */

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>
#include <QStyleOptionGraphicsItem>
#include <QPrinter>
#include <QList>

#include <graphviz/gvc.h>

#include "itf_garrangement_moc.h"
#include "itf_state_transition.h"
#include "itf_debug.h"

#include "sim_interface.h"

#include "prefix_tree.h"


#include "mex.h"


GraphicArrangement::GraphicArrangement() {
	gvc = gvContext();

	/* Create a simple digraph */
	//gvc_graph = agmemread("digraph G{2->1; 3->2; 1->3;}");
	gvc_graph = agopen("x.dot", AGDIGRAPH);
    
	//agset(gvc_graph, "dpi", "96,0");

}

GraphicArrangement::~GraphicArrangement() {
	gvFreeLayout(gvc, gvc_graph);
	agclose(gvc_graph);
	gvFreeContext(gvc);
}

void GraphicArrangement::setLayout(char *type) {
	gvLayout(gvc, gvc_graph, type);
}

// This function uses the prefix_tree.c file
void GraphicArrangement::fromTrie(psa *trie) {
    
    unsigned int i;
    ntrieNode *node;
    
    assert(trie != NULL);
    
    // The empty trie case
    if (trie->n < 1)
        return;
    
    // Construct States 
    // --------------------------------------------------------------------
    for(i=0; i < trie->n; i++) {
        // If node is removed does not create item object
        if (trie->nodeArray[i]->removed == 0)
        {
            map_state_id2State.insert(trie->nodeArray[i]->nid, new State(trie->nodeArray[i]->nid, gvc_graph));
        }
    }
    
    // Construct Events 
    // --------------------------------------------------------------------
    for(i=0; i < trie->n; i++) {
        // If node is removed does not create item object
        if (trie->nodeArray[i]->removed == 0) {
            // Construct Events
            NEDTRIE_FOREACH(node, ntrie_s, trie->nodeArray[i]->child) {
                /*DEBUG_PRINT((FDEBUG, "%d -- %d -- %d\n", node->nid, node->key, node->node->nid));*/
                if (map_state_id2State.contains(trie->nodeArray[i]->nid) && map_state_id2State.contains(node->node->nid))
                {
                    map_event_id2Event.insert(map_event_id2Event.count()+1, new Event(map_state_id2State.value(trie->nodeArray[i]->nid), map_state_id2State.value(node->node->nid), node->key, gvc_graph, node));
                }
                else
                {
                    mexErrMsgTxt("itf_arrangement: The state indentifier not match.");
                }
            }
        }
    }
}

void GraphicArrangement::fromMc(markovChain mc) {
    
    unsigned int i,j,z;
    double value;
    
    /* Create the states */
    /* Create nodes */
    for(i=0; i < mc.n_S; i++) {
        map_state_id2State.insert(mc.S[i], new State(mc.S[i], gvc_graph));
    }
    /* End the creation of states*/
    
    /* Creation of transictions */
    for (z=0; z<mc.n_E; z++)
        for (j=0; j<mc.n_S; j++)
            for (i=0; i<mc.n_S; i++) {
                value = mc.p[(i+(j*mc.n_S))+(mc.n_S*mc.n_S*z)];
                if (value > 0)
                {
                    map_event_id2Event.insert(map_event_id2Event.count()+1, new Event(map_state_id2State.value(j+1), map_state_id2State.value(i+1), z+1, gvc_graph, NULL));
                }
            }
    /* End creation */
}

QRect GraphicArrangement::boundingRect()
{
    double DotDefaultDPI = 72;
	double dpi = 96;
    
    return QRect(gvc_graph->u.bb.LL.x*(dpi/DotDefaultDPI), gvc_graph->u.bb.LL.y*(dpi/DotDefaultDPI),
                 gvc_graph->u.bb.UR.x*(dpi/DotDefaultDPI), gvc_graph->u.bb.UR.y*(dpi/DotDefaultDPI));
}

QMap<int, State*> GraphicArrangement::getStateItems()
{
    return map_state_id2State;
}

QMap<int, Event*> GraphicArrangement::getEventItems()
{
    return map_event_id2Event;
}

void GraphicArrangement::display(QGraphicsScene *scene) {
	
	unsigned int i;
    char tmp[1000];
    
    State *elItem;
    QPainterPath *ppath;
    Event *pathItem;
    
    QMapIterator<int, State*> it_st(map_state_id2State);
    QMapIterator<int, Event*> it_ev(map_event_id2Event);
    
    mexPrintf("Display...\n");
    
    while (it_st.hasNext()) {
        it_st.next();
        
        it_st.value()->draw(scene);
	}
    
    mexPrintf("Nodes Added ...\n");
    
    while (it_ev.hasNext()) {
        it_ev.next();
        
        it_ev.value()->draw(scene);
    }
    
    mexPrintf("Transitions added\n");
    
}

